namespace C1.Win.C1FlexGrid
{
    using System;
    using System.Drawing;

    internal class GridSelHandler
    {
        internal RowCol _col;
        internal RowCol _colsel;
        internal GridModel _grid;
        internal SelectionModeEnum _mode;
        internal CellRange _newRange;
        internal CellRange _oldRange;
        internal CellRange _range;
        internal RowCol _row;
        internal RowCol _rowsel;
        internal bool _selCancel;

        internal GridSelHandler(GridModel grid)
        {
            this._grid = grid;
            this._mode = SelectionModeEnum.Default;
            this._range = new CellRange(this._grid, -2, -2);
        }

        internal bool CanExtend()
        {
            switch (this._mode)
            {
                case SelectionModeEnum.Cell:
                case SelectionModeEnum.Row:
                case SelectionModeEnum.Column:
                    return false;
            }
            return true;
        }

        internal bool FastInvalidateOK()
        {
            switch (this._mode)
            {
                case SelectionModeEnum.Default:
                case SelectionModeEnum.Cell:
                case SelectionModeEnum.CellRange:
                    return true;
            }
            return false;
        }

        internal Point GetCursor()
        {
            return new Point(this._range.c1, this._range.r1);
        }

        internal CellRange GetRange()
        {
            return this._range;
        }

        internal bool HasCursor()
        {
            return !this._grid.IsBadRowCol(this._range.r1, this._range.c1);
        }

        internal bool IsBadRange(CellRange rg)
        {
            if (((rg.r1 >= -2) && (rg.c1 >= -2)) && ((rg.r2 >= -2) && (rg.c2 >= -2)))
            {
                GridModel model = this._grid;
                int num = model._rows.Count - 1;
                if ((rg.r1 > num) || (rg.r2 > num))
                {
                    return true;
                }
                num = model._cols.Count - 1;
                if ((rg.c1 <= num) && (rg.c2 <= num))
                {
                    return false;
                }
            }
            return true;
        }

        internal bool IsCellCursor(int row, int col)
        {
            return ((row == this._range.r1) && (col == this._range.c1));
        }

        internal bool IsCellSelected(int row, int col)
        {
            bool flag = this._grid.IsCellFixed(row, col);
            switch (this._mode)
            {
                case SelectionModeEnum.Default:
                    if (!this._range.Contains(row, col))
                    {
                        break;
                    }
                    return true;

                case SelectionModeEnum.Cell:
                    if ((row != this._range.r1) || (col != this._range.c1))
                    {
                        break;
                    }
                    return true;

                case SelectionModeEnum.CellRange:
                    if (!this._range.Contains(row, col))
                    {
                        break;
                    }
                    return true;

                case SelectionModeEnum.Row:
                    if ((row != this._range.r1) || flag)
                    {
                        break;
                    }
                    return true;

                case SelectionModeEnum.RowRange:
                    if (!this._range.ContainsRow(row) || flag)
                    {
                        break;
                    }
                    return true;

                case SelectionModeEnum.Column:
                    if ((col != this._range.c1) || flag)
                    {
                        break;
                    }
                    return true;

                case SelectionModeEnum.ColumnRange:
                    if (!this._range.ContainsCol(col) || flag)
                    {
                        break;
                    }
                    return true;
            }
            GridModel model = this._grid;
            if (model.IsCellFixed(row, col))
            {
                return false;
            }
            if (!model._rows[row].Selected)
            {
                return model._cols[col].Selected;
            }
            return true;
        }

        internal void SaveRange(CellRange rg)
        {
            GridModel model = this._grid;
            this._range = rg;
            this._row = model.IsBadRow(rg.r1) ? null : ((RowCol) model._rows[rg.r1]);
            this._rowsel = model.IsBadRow(rg.r2) ? null : ((RowCol) model._rows[rg.r2]);
            this._col = model.IsBadCol(rg.c1) ? null : ((RowCol) model._cols[rg.c1]);
            this._colsel = model.IsBadCol(rg.c2) ? null : ((RowCol) model._cols[rg.c2]);
        }

        internal void Select(C1FlexGridBase view, CellRange newRange, bool show)
        {
            if (!newRange.Equals(this._range))
            {
                if (this.IsBadRange(newRange))
                {
                    throw new IndexOutOfRangeException("Invalid parameters for Select method.");
                }
                if (view.FinishEditing())
                {
                    this._oldRange = this._range;
                    this._newRange = newRange;
                    this._grid.NotifyViews(GridChangedTypeEnum.BeforeSelChange);
                    if (!this._selCancel)
                    {
                        if (this._mode == SelectionModeEnum.ListBox)
                        {
                            int num = -1;
                            int num2 = -1;
                            RowCollection rows = this._grid._rows;
                            for (int i = 0; i < rows.Count; i++)
                            {
                                bool flagsOn = newRange.ContainsRow(i);
                                if (rows[i].ChangeFlags(RowColFlags.Selected, flagsOn))
                                {
                                    if (num < 0)
                                    {
                                        num = i;
                                    }
                                    num2 = i;
                                }
                            }
                            this._grid.NotifyViews(GridChangedTypeEnum.RowSelected, num, -1, num2, -1);
                        }
                        if (newRange.Equals(this._range))
                        {
                            if (show)
                            {
                                view.ShowCell(this._range.r2, this._range.c2);
                            }
                        }
                        else
                        {
                            switch (this._mode)
                            {
                                case SelectionModeEnum.Row:
                                case SelectionModeEnum.RowRange:
                                {
                                    int @fixed = view.Cols.Fixed;
                                    int num5 = view.Cols.Count - 1;
                                    this._grid.NotifyViews(GridChangedTypeEnum.RepaintRange, this._range.r1, @fixed, this._range.r2, num5);
                                    this._grid.NotifyViews(GridChangedTypeEnum.RepaintRange, newRange.r1, @fixed, newRange.r2, num5);
                                    break;
                                }
                                case SelectionModeEnum.Column:
                                case SelectionModeEnum.ColumnRange:
                                {
                                    int num6 = view.Rows.Fixed;
                                    int num7 = view.Rows.Count - 1;
                                    this._grid.NotifyViews(GridChangedTypeEnum.RepaintRange, num6, this._range.c1, num7, this._range.c2);
                                    this._grid.NotifyViews(GridChangedTypeEnum.RepaintRange, num6, newRange.c1, num7, newRange.c2);
                                    break;
                                }
                                case SelectionModeEnum.ListBox:
                                    this._grid.NotifyViews(GridChangedTypeEnum.RepaintRange, this._range.r1, this._range.c1);
                                    this._grid.NotifyViews(GridChangedTypeEnum.RepaintRange, newRange.r1, newRange.c1);
                                    break;

                                default:
                                {
                                    CellRange rg = this._range.Delta(newRange);
                                    if (rg.IsValid)
                                    {
                                        this._grid.NotifyViews(GridChangedTypeEnum.RepaintRange, rg);
                                    }
                                    else
                                    {
                                        this._grid.NotifyViews(GridChangedTypeEnum.RepaintRange, this._range);
                                        this._grid.NotifyViews(GridChangedTypeEnum.RepaintRange, newRange);
                                    }
                                    break;
                                }
                            }
                            this.SaveRange(newRange);
                            this._grid.NotifyViews(GridChangedTypeEnum.AfterSelChange);
                            if (show)
                            {
                                view.ShowCell(this._range.r2, this._range.c2);
                            }
                        }
                    }
                }
            }
        }

        internal void SelectList(C1FlexGridBase view, int row, int col, bool select, RowCollection selRows)
        {
            GridModel model = this._grid;
            RowCollection rows = model._rows;
            if (view.FinishEditing())
            {
                if (selRows == null)
                {
                    this._oldRange = this._newRange = this._range;
                    this._newRange.r1 = this._newRange.r2 = row;
                    this._grid.NotifyViews(GridChangedTypeEnum.BeforeSelChange);
                    if (!this._selCancel)
                    {
                        model.NotifyViews(GridChangedTypeEnum.RowSelected, this._range.r1, -1, this._range.r2, -1);
                        this._range.r1 = this._range.r2 = row;
                        if (col >= model._cols.Fixed)
                        {
                            this._range.c1 = this._range.c2 = col;
                        }
                        rows[row].Selected = select;
                        this._grid.NotifyViews(GridChangedTypeEnum.AfterSelChange);
                    }
                }
                else
                {
                    int num2 = -1;
                    int num3 = -1;
                    this._oldRange = this._newRange = this._range;
                    this._newRange.r2 = row;
                    this._grid.NotifyViews(GridChangedTypeEnum.BeforeSelChange);
                    if (!this._selCancel)
                    {
                        int topRow = this._range.TopRow;
                        while (topRow <= this._range.BottomRow)
                        {
                            if (!this._newRange.ContainsRow(topRow))
                            {
                                bool flagsOn = selRows.Contains(rows[topRow]);
                                if (rows[topRow].ChangeFlags(RowColFlags.Selected, flagsOn))
                                {
                                    if (num2 < 0)
                                    {
                                        num2 = topRow;
                                    }
                                    num3 = topRow;
                                }
                            }
                            topRow++;
                        }
                        this._range = this._newRange;
                        for (topRow = this._range.TopRow; topRow <= this._range.BottomRow; topRow++)
                        {
                            if (rows[topRow].ChangeFlags(RowColFlags.Selected, select))
                            {
                                if (num2 < 0)
                                {
                                    num2 = topRow;
                                }
                                num3 = topRow;
                            }
                        }
                        this._grid.NotifyViews(GridChangedTypeEnum.RowSelected, num2, -1, num3, -1);
                        this._grid.NotifyViews(GridChangedTypeEnum.AfterSelChange);
                        view.ShowCell(row, col);
                    }
                }
            }
        }

        internal void Validate()
        {
            this._newRange = this._oldRange = this._range;
            GridModel model = this._grid;
            this.ValidateIndex(model._rows, ref this._newRange.r1, ref this._row);
            this.ValidateIndex(model._rows, ref this._newRange.r2, ref this._rowsel);
            this.ValidateIndex(model._cols, ref this._newRange.c1, ref this._col);
            this.ValidateIndex(model._cols, ref this._newRange.c2, ref this._colsel);
            if (!this._newRange.Equals(this._oldRange))
            {
                this._grid.NotifyViews(GridChangedTypeEnum.BeforeSelChange);
                this._range = this._newRange;
                this._grid.NotifyViews(GridChangedTypeEnum.AfterSelChange);
            }
        }

        internal void ValidateIndex(RowColCollection coll, ref int index, ref RowCol item)
        {
            if (index == -1)
            {
                item = null;
            }
            else if ((index < coll.Fixed) && (coll.Count > coll.Fixed))
            {
                index = coll.Fixed;
                item = coll[index];
            }
            else if (((index < 0) || (index >= coll.Count)) || (coll[index] != item))
            {
                if (item != null)
                {
                    int num = coll._items.IndexOf(item);
                    if (num > -1)
                    {
                        index = num;
                        return;
                    }
                }
                if (index >= coll.Count)
                {
                    index = coll.Count - 1;
                    if (index <= coll.Fixed)
                    {
                        index = -2;
                    }
                }
                item = (index > -1) ? coll[index] : null;
            }
        }

        internal SelectionModeEnum SelectionMode
        {
            get
            {
                return this._mode;
            }
            set
            {
                if (this._mode != value)
                {
                    if (this._mode == SelectionModeEnum.ListBox)
                    {
                        RowCollection rows = this._grid._rows;
                        for (int i = 0; i < this._grid._rows.Count; i++)
                        {
                            rows[i].SetFlags(RowColFlags.Selected, false);
                        }
                    }
                    this._mode = value;
                    this._grid.NotifyViews(GridChangedTypeEnum.RepaintGrid);
                }
            }
        }
    }
}

